﻿using LxBasic;

namespace LxCore
{
    public struct FvInnCell
    {
        //拓扑关系
        public int InnOFaceEnd;
        public int InnNFaceEnd;
        public int[] AdjFaces;
        //几何信息，内部
        public double Volumn;
        public Vector3d Center;
        public SymMatrixR3C3 LSQMatrix;
        public void CalGeometry(FvInnFace[] innFaces, FvBouFace[] bouCFaces)
        {
            CellGeomCalc c = new CellGeomCalc();
            int i1 = 0;
            for (; i1 < InnOFaceEnd; i1++)
            {
                ref FvInnFace face = ref innFaces[AdjFaces[i1]];
                c.AddFace(face.Normal, face.Center);
            }
            for (; i1 < InnNFaceEnd; i1++)
            {
                ref FvInnFace face = ref innFaces[AdjFaces[i1]];
                c.AddFaceReversed(face.Normal, face.Center);
            }
            for (; i1 < AdjFaces.Length; i1++)
            {
                ref var face = ref bouCFaces[AdjFaces[i1]];
                c.AddFace(face.Normal, face.Center);
            }
            (Volumn, Center) = c.GetResult();
        }

        public void CalLSQMatrix(FvInnFace[] innFaces, FvBouFace[] bouCFaces)
        {
            LSQMatrix = new();
            int i1 = 0;
            for (; i1 < InnOFaceEnd; i1++)
            {
                AddVector_FromThisToAdjacent(ref LSQMatrix, innFaces[AdjFaces[i1]].OToN);
            }
            for (; i1 < InnNFaceEnd; i1++)
            {
                AddVector_FromThisToAdjacent(ref LSQMatrix, -innFaces[AdjFaces[i1]].OToN);
            }
            for (; i1 < AdjFaces.Length; i1++)
            {
                AddVector_FromThisToAdjacent(ref LSQMatrix, bouCFaces[AdjFaces[i1]].OToN);
            }
            LSQMatrix.Inverse();
            void AddVector_FromThisToAdjacent(ref SymMatrixR3C3 m, Vector3d v)
            {
                double lengthWeight = 1 / v.Length();
                m.a11 += lengthWeight * v.X * v.X;
                m.a22 += lengthWeight * v.Y * v.Y;
                m.a33 += lengthWeight * v.Z * v.Z;
                m.a21 += lengthWeight * v.X * v.Y;
                m.a31 += lengthWeight * v.X * v.Z;
                m.a32 += lengthWeight * v.Y * v.Z;
            }
        }
        public unsafe Vector3d CalGradient_LeastSquare(FvInnFace[] innFaces, FvBouFace[] bouCFaces, double[] xInn, double[] xBou)
        {
            Vector3d v3d = new();
            fixed (int* start = AdjFaces)
            {
                int* adjf = start, endp1 = start + InnOFaceEnd;
                for (; adjf < endp1; ++adjf)
                {
                    ref var f = ref innFaces[*adjf];
                    v3d += (xInn[f.NSideCell] - xInn[f.OSideCell]) / f.OToNLength * f.OToN;
                }
                endp1 = start + InnNFaceEnd;
                for (; adjf < endp1; ++adjf)
                {
                    ref var f = ref innFaces[*adjf];
                    v3d += (xInn[f.NSideCell] - xInn[f.OSideCell]) / f.OToNLength * f.OToN;
                }
                endp1 = start + AdjFaces.Length;
                for (; adjf < endp1; ++adjf)
                {
                    ref var f = ref bouCFaces[*adjf];
                    v3d += (xBou[*adjf] - xInn[f.OSideCell]) / f.OToNLength * f.OToN;
                }
            }
            return Matrix3dMath.Product(LSQMatrix, v3d);
        }
        public unsafe double CalIfOwnerAddElseMunus(double[] innFaceData, double[] bouFaceData)
        {
            double result = 0;
            fixed (int* start = AdjFaces)
            {
                int* adjf = start, endp1 = start + InnOFaceEnd;
                for (; adjf < endp1; ++adjf)
                {
                    result += innFaceData[*adjf];
                }
                endp1 = start + InnNFaceEnd;
                for (; adjf < endp1; ++adjf)
                {
                    result -= innFaceData[*adjf];
                }
                endp1 = start + AdjFaces.Length;
                for (; adjf < endp1; ++adjf)
                {
                    result += bouFaceData[*adjf];
                }
            }
            return result;
        }
 

    }
}
//public unsafe double CalAllAdd(double[] innOFaceData, double[] innNFaceData, double[] bouCFaceData)
//{
//    double result = 0;
//    fixed (int* start = AdjFaces)
//    {
//        int* adjf = start, endp1 = start + InnOFaceEnd;
//        for (; adjf < endp1; ++adjf)
//        {
//            result += innOFaceData[*adjf];
//        }
//        endp1 = start + InnNFaceEnd;
//        for (; adjf < endp1; ++adjf)
//        {
//            result += innNFaceData[*adjf];
//        }
//        endp1 = start + AdjFaces.Length;
//        for (; adjf < endp1; ++adjf)
//        {
//            result += bouCFaceData[*adjf];
//        }
//    }
//    return result;
//}